﻿using UnityEngine;
using System.Collections;
using System.Collections.Generic;

using NSFileVersionMgr;
public interface IVersionStrategy
{
    string key { get; }
    /// <summary>
    /// 服务器上有新版本
    /// </summary>
    void ServerValid();

    /// <summary>
    /// 本地已缓存最新版本
    /// </summary>
    void LocalValid();

    /// <summary>
    /// apk包自带的版本就是最新版本
    /// </summary>
    void DefaultValid();

    // 服务器上以删除配置
    void ServerNull();
}

/// <summary>
/// 文件版本管理
/// local : 本地版本文件
/// server ： 服务器版本文件
/// defaultVersion : apk版本
/// 
/// 
/// 
/// </summary>
public class FileVersionMgr : ISubModule {

    FileVersionMgr_Private realObj;
    FileVersionMgr_Private realObj_version; // 按版本检测

    #region SingleTon
    static FileVersionMgr s_Instance;
    public static FileVersionMgr Instance {
        get
        {
            if(s_Instance == null)
            {
                s_Instance = new FileVersionMgr();
            }

            return s_Instance;
        }
    }
    #endregion

    /// <summary>
    /// 检查最新版本
    ///     如果此时version.txt已经下载完成，则直接判断处理。
    ///     否则，加入versionCheckList队列，等到下载结束后再处理
    ///     
    /// </summary>
    /// <param name="v"></param>
    public void CheckVersion(IVersionStrategy v)
    {
        realObj.CheckVersion(v);
    }

    /// <summary>
    /// 下载完新数据后，更新本地存储的版本号
    /// </summary>
    /// <param name="v"></param>
    public void WriteLocalVersion(IVersionStrategy v)
    {
        realObj.WriteLocalVersion(v);
    }

    public void CheckVersion_Version(IVersionStrategy v)
    {
        realObj_version.CheckVersion(v);
    }

    /// <summary>
    /// 下载完新数据后，更新本地存储的版本号
    /// </summary>
    /// <param name="v"></param>
    public void WriteLocalVersion_Version(IVersionStrategy v)
    {
        realObj_version.WriteLocalVersion(v);
    }

    void IPurge.PrePurge()
    {
        
    }

    void IPurge.Purge()
    {
        s_Instance = null;
    }

    void ISubModule.Init()
    {
        realObj_version = new FileVersionMgr_Private("version_v", "/version.txt");
        realObj_version.Init();
    }

    void ISubModule.Start()
    {

    }

    void IUpdate.Update()
    {

    }
}

namespace NSFileVersionMgr
{
    class FileVersionMgr_Private
    {
        VersionData local;

        VersionData server;

        string mLocalPath;

        string mServerPath;

        /// <summary>
        /// 本地缓存版本名：不加后缀;
        /// 服务器版本名： 加后缀;
        /// </summary>
        /// <param name="localPath"></param>
        /// <param name="serverPath"></param>
        public FileVersionMgr_Private(string localPath, string serverPath)
        {
            mLocalPath = localPath;
            mServerPath = serverPath;
        }

        public bool error { get; protected set; }

        public bool downloadFinish { get; protected set; }

        List<IVersionStrategy> versionCheckList = new List<IVersionStrategy>();

        const float outTime = 5; // 超时时间

        string defaultVersion { get { return CompileConfig.Instance.bundleVersion; } }


        public void Init()
        {
            downloadFinish = false;
            error = true;
            // 启动时，下载version.txt
            string url = FileDownloadMgr.DefaultPath + mServerPath;
            FileDownloadMgr.Download(url, cb_DownFinish, outTime);

            LoadVersionFromLocal();
        }

        /// <summary>
        /// 服务下文件下载完成;
        /// </summary>
        /// <param name="ret"></param>
        /// <param name="www"></param>
        void cb_DownFinish(DownloadResult ret, WWW www)
        {
            downloadFinish = true;

            if (ret == DownloadResult.Success)
            {
                byte[] context = www.bytes;
                error = false;
                server = ParseVersionFile(context);
            }

            handleOnWWWFinish();
        }

        /// <summary>
        /// 获取最新的版本
        /// </summary>
        /// <param name="key"></param>
        /// <returns>
        ///     1、Server
        ///     2、本地备份
        ///     3、apk包自带
        /// </returns>
        VersionState GetNewestVersion(string key)
        {
            if (error)
            {
                return GetNewestVersionFromLocal(key);
            }
            else
            {
                string sVersion = server.GetVersion(key);
                if (string.IsNullOrEmpty(sVersion)) return VersionState.ServerNone;
                string lVersion = local.GetVersion(key);
                if (defaultVersion.CompareTo(lVersion) == 0 || defaultVersion.CompareTo(sVersion) == 0)
                {
                    Debugger.LogError(string.Format("error config for key : {0} in file {1}", key, mServerPath));
                    return VersionState.DefaultVersion;
                }

                string maxVresion = lVersion;
                VersionState result = VersionState.Local;
                if (defaultVersion.CompareTo(maxVresion) == 1)
                {
                    maxVresion = defaultVersion;
                    result = VersionState.DefaultVersion;
                }

                if (sVersion.CompareTo(maxVresion) == 1)
                {
                    maxVresion = sVersion;
                    result = VersionState.Server;
                }

                return result;
            }
        }

        public VersionState GetNewestVersionFromLocal(string key)
        {
            string version = local.GetVersion(key);
            if (defaultVersion.CompareTo(version) == -1)
                return VersionState.Local;
            else return VersionState.DefaultVersion;
        }

        public void WriteLocalVersion(IVersionStrategy v)
        {
            // 此函数必须在新的version.txt下载成功后，才能调用
            Debugger.Assert(server != null, "serer must not be null");
            string sV = server.GetVersion(v.key);
            string lV = local.GetVersion(v.key);
            if (sV == lV) return;

            if (string.IsNullOrEmpty(sV))
                local.DeleteVersion(v.key);
            else
                local.SetVersion(v.key, sV);
            string result = local.Serialize();
            if (string.IsNullOrEmpty(result))
                TextReadAndWrite.WriteToPersistentPath(mLocalPath, null);
            else
                TextReadAndWrite.WriteToPersistentPath(mLocalPath, System.Text.Encoding.UTF8.GetBytes(result));
        }

        static string Max(string left, string right)
        {
            if (string.IsNullOrEmpty(left))
                return right;

            if (string.IsNullOrEmpty(right))
                return left;

            if (left.CompareTo(right) == 1)
                return left;

            return right;
        }

        /// <summary>
        /// 检查是否有新版本
        ///     如果此时version.txt已经下载下来，则直接判断处理。
        ///     否则，加入versionCheckList队列，等到下载结束后再处理
        /// </summary>
        /// <param name="v"></param>
        public void CheckVersion(IVersionStrategy v)
        {
            if (downloadFinish)
            {
                _CheckVersionImmed(v);
            }
            else
            {
                versionCheckList.Add(v);
            }
        }

        /// <summary>
        /// 立即处理版本检查
        /// </summary>
        /// <param name="v"></param>
        void _CheckVersionImmed(IVersionStrategy v)
        {
            var ret = GetNewestVersion(v.key);
            switch (ret)
            {
                case VersionState.Server:
                    {
                        v.ServerValid();
                        break;
                    }
                case VersionState.Local:
                    {
                        v.LocalValid();
                        break;
                    }
                case VersionState.DefaultVersion:
                    {
                        v.DefaultValid();
                        break;
                    }
                case VersionState.ServerNone:
                    {
                        v.ServerNull();
                        break;
                    }
                default:
                    Debugger.LogError(string.Format("error return {0} for key : {1}", ret, v.key));
                    break;
            }
        }

        void handleOnWWWFinish()
        {
            for (int i = 0; i < versionCheckList.Count; i++)
            {
                _CheckVersionImmed(versionCheckList[i]);
            }

            versionCheckList.Clear();
        }

        // 解析本地版本信息
        void LoadVersionFromLocal()
        {
            ByteReader reader = new ByteReader(TextReadAndWrite.LoadFromPersistenPath(mLocalPath));
            local = VersionData.Create(reader.ReadDictionary());
        }

        static VersionData ParseVersionFile(byte[] fileContext, string defVersion = "")
        {
            bool avalidText = (fileContext != null && fileContext.Length != 0);
            Debugger.Assert(avalidText, "error fileCOntext");

            if (!avalidText)
                return null;

            ByteReader reader = new ByteReader(fileContext);
            Dictionary<string, string> context = reader.ReadDictionary();
            Debugger.Assert(context != null, "parse version File Error");

            // 去除注释行
            CommonFunctions.FilterCommend(context);

            return VersionData.Create(context, defVersion);
        }

    }

    /// <summary>
    /// 管理版本号
    /// </summary>
    class VersionData
    {
        string defaultVersion;
        Dictionary<string, string> versionDict;

        protected VersionData(Dictionary<string, string> dict, string defVersion = "")
        {
            defaultVersion = defVersion;
            versionDict = dict;
        }

        public static VersionData Create(Dictionary<string, string> dict, string defVersion = "")
        {
            return new VersionData(dict, defVersion);
        }

        public void SetDefVersion(string version)
        {
            defaultVersion = version;
        }

        public string GetVersion(string key)
        {
            if (versionDict == null)
                return defaultVersion;

            string ret;
            if (versionDict.TryGetValue(key, out ret))
                return ret;

            return defaultVersion;
        }

        public void SetVersion(string key, string version)
        {
            if (versionDict == null)
                versionDict = new Dictionary<string, string>();

            versionDict[key] = version;
        }

        public string Serialize()
        {
            if (versionDict == null || versionDict.Count == 0)
                return null;

            return SerializeTool.DictToString(versionDict, "=", "\n");
        }

        public void DeleteVersion(string key)
        {
            versionDict.Remove(key);
        }
    }


    enum VersionState
    {
        Server = 1,
        Local = 2,
        DefaultVersion = 3,
        ServerNone = 4, // 服务器上为空。空表示服务器已删除相关配置。所以本地也要删除。
    }
}